/**
    Copyright (C) 2011  Alexander Vollmer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.jefb.web.controller;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.annotation.PostConstruct;

import org.jefb.annotations.EnabledHavingRights;
import org.jefb.entity.DestinationEntity;
import org.jefb.entity.FileEntity;
import org.jefb.entity.dto.TransmissionStatus;
import org.jefb.sec.entity.UserRight;
import org.jefb.service.ICommonPersistenceService;
import org.jefb.service.IFileRegisterService;
import org.jefb.service.IFileSystemService;
import org.jefb.service.ITransmissionStatusService;
import org.jefb.service.IUserSessionService;
import org.jefb.service.exception.FileSystemException;
import org.jefb.service.exception.MLException;
import org.jefb.util.JefbUtils;
import org.jefb.web.model.DirectoryMananagerModel;
import org.jefb.web.model.FileDataHolder;
import org.jefb.web.model.MessagesModel;
import org.jefb.web.model.entity.Message;
import org.jefb.web.model.entity.MessageType;
import org.jefb.web.util.ComponentsUtil;
import org.jefb.web.util.Icons;
import org.jefb.web.util.WebUtil;
import org.jefb.web.util.ZKUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.zkoss.util.media.Media;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.KeyEvent;
import org.zkoss.zk.ui.event.SelectEvent;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.databind.BindingListModelList;
import org.zkoss.zul.Button;
import org.zkoss.zul.Filedownload;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Label;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Row;
import org.zkoss.zul.RowRenderer;
import org.zkoss.zul.Tabbox;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Toolbarbutton;

@org.springframework.stereotype.Component
@Scope("prototype")
public class DirectoryManagerController extends GenericForwardComposer
		implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	private boolean isCutButtonClicked = false;
	
	//services
	@Autowired
	private IFileRegisterService fileRegisterService;
	@Autowired
	private IFileSystemService fileSystemService;
	@Autowired
	private ITransmissionStatusService transmissionStatusService;
	@Autowired
	private ICommonPersistenceService commonPersistenceService;
	
	//models
	@Autowired
	private DirectoryMananagerModel directoryManagerModel;
	@Autowired
	private IUserSessionService userSessionService;
	@Autowired
	private MessagesModel messagesModel;

	private FileListModel fileListModel;
	
	// UI components
	protected Tabbox fmTabbox;
	protected Listbox fileList;
	protected Textbox description;

	protected Button backButton;
	protected Button refreshButton;
	protected Textbox currentPathTextbox;

	@EnabledHavingRights({UserRight.DOWNLOAD_FILE})
	protected Toolbarbutton downloadFileButton;
	
	@EnabledHavingRights({UserRight.DELETE_FILE})
	protected Toolbarbutton deleteFileButton;
	
	@EnabledHavingRights({UserRight.MOVE_FILE})
	protected Toolbarbutton markForCopyButton;
	
	@EnabledHavingRights({UserRight.MOVE_FILE})
	protected Toolbarbutton markForCutButton;
	
	@EnabledHavingRights({UserRight.MOVE_FILE})
	protected Toolbarbutton pasteFileButton;
	
	@EnabledHavingRights({UserRight.ZIP_FILE})
	protected Toolbarbutton zipFileButton;
	
	@EnabledHavingRights({UserRight.RENAME_FILE})
	protected Toolbarbutton renameButton;
	
	@EnabledHavingRights({UserRight.UPLOAD_FILE})
	protected Button uploadButton;

	// navigation buttons
	protected Toolbarbutton navBackButton;
	protected Toolbarbutton navUpButton;
	protected Toolbarbutton navForwardButton;
	protected Toolbarbutton navHomeButton;

	protected Grid fileInfoGrid;

	public DirectoryManagerController() {
	}

	@PostConstruct
	public void init() {
		directoryManagerModel.setWorkspace(userSessionService.getHomeDir());
		// init root directories
		fileListModel = new FileListModel(new ArrayList<FileDataHolder>());
		directoryManagerModel.addPropertyChangeListener(
				DirectoryMananagerModel.CURRENT_DIR_PROPERTY,
				new PropertyChangeListener() {
					public void propertyChange(PropertyChangeEvent arg0) {
						initFileListModel();
						refreshNavButtons();
					}
				});
	}

	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		initFileListModel();
	}

	public void onClick$showHiddenCheckbox(Event event) {
		initFileListModel();
	}

	public void initFileListModel() {
		List<File> files = null;
		try {
			File currentDirectoryFile = new File(userSessionService.getHomeDir()+
					directoryManagerModel.getCurrentDir());
			files = fileSystemService.getFileList(currentDirectoryFile,
					directoryManagerModel.getShowHidden());
			List<FileDataHolder> fileDataHolderList = new ArrayList<FileDataHolder>();
			for (File file : files) {
				FileDataHolder fileDataHolder = new FileDataHolder(file);
				fileDataHolder.setFileName(file.getName());
				fileDataHolder.setIsFile(file.isFile());
				fileDataHolderList.add(fileDataHolder);
			}
			Collections.sort(fileDataHolderList);
			fileListModel.clear();
			fileListModel.addAll(fileDataHolderList);
			fileList.setModel(fileListModel);
			fileList.setItemRenderer(fileListModel);

			currentPathTextbox.setValue(directoryManagerModel.getCurrentDir());
			fileInfoGrid.setVisible(false);
			directoryManagerModel.setSelectedFile(null);
			setFileStatusPanelVisibility();
		} catch (FileSystemException fse) {
			handleMLexception(fse);
			onClick$navBackButton(null);
		}
	}

	public void onClick$newFolderButton(Event event) {
		FileDataHolder fileHolder = new FileDataHolder();
		fileHolder.setIsFile(false);
		fileListModel.add(fileHolder);
	}

	public void onClick$newFileButton(Event event) {
		FileDataHolder fileHolder = new FileDataHolder();
		fileHolder.setIsFile(true);
		fileListModel.add(fileHolder);
	}

	public void onClick$refreshButton(Event e) {
		initFileListModel();
		setFileStatusPanelVisibility();
	}
	
	public void onClick$unzipFileButton(Event e){
		if(getDirectoryManagerModel().getSelectedFile()!=null){
			fileSystemService.unzipFile(getDirectoryManagerModel().getSelectedFile().getFile());
			initFileListModel();
		}
	}

	public void onClick$renameButton(Event event) {
		if (fileList.getSelectedCount() > 0) {
			Listitem selectedItem = fileList.getSelectedItem();
			List<?> children = selectedItem.getChildren();
			Listcell nameCell = (Listcell) children.get(0);
			nameCell.setLabel(null);
			final FileDataHolder selectedFile = directoryManagerModel
					.getSelectedFile();
			final Textbox editBox = new Textbox(selectedFile.getFileName());
			editBox.setParent(nameCell);
			editBox.setFocus(true);
			editBox.setWidth("98%");
			editBox.addEventListener(Events.ON_OK, new EventListener() {
				public void onEvent(Event event) throws Exception {
					renameFile(selectedFile.getFile(), editBox.getValue());
				}
			});
			editBox.addEventListener(Events.ON_BLUR, new EventListener() {
				public void onEvent(Event event) throws Exception {
					renameFile(selectedFile.getFile(), editBox.getValue());
				}
			});
			editBox.addEventListener(Events.ON_CANCEL, new EventListener() {
				public void onEvent(Event event) throws Exception {
					initFileListModel();
				}
			});
		}
	}

	private void renameFile(File origFile, String newName) {
		try {
			fileSystemService.renameFile(origFile, newName,
					directoryManagerModel.getWorkspace(),
					userSessionService.getHomeDir());
		} catch (FileSystemException e) {
			handleMLexception(e);
		}
		initFileListModel();
	}

	public void onClick$markForCopyButton(Event e) {
		isCutButtonClicked = false;
		markForPaste();
	}

	public void onClick$markForCutButton(Event e) {
		isCutButtonClicked = true;
		markForPaste();
	}

	private void markForPaste() {
		FileDataHolder selectedFile = directoryManagerModel.getSelectedFile();
		if (selectedFile != null && selectedFile.getFile() != null) {
			directoryManagerModel.setFileToCopy(selectedFile.getFile());
		}
	}

	public void onClick$pasteFileButton(Event event) {
		final File fileToCopy = directoryManagerModel.getFileToCopy();
		String absolutePath = JefbUtils.extractPath(fileToCopy);
		if (fileSystemService.containsFile(
				new File(directoryManagerModel.getWorkspaceDirectory()),
				fileToCopy)
				&& !absolutePath.equals(directoryManagerModel
						.getWorkspaceDirectory())) {
			try {
				// TODO make message box optional -->user settings
				Messagebox.show(ZKUtils.getLabel(
						"filemanager.msg.file_already_exists",
						fileToCopy.getName()), ZKUtils
						.getLabel("filemanager.prompt.file_already_exists"),
						Messagebox.YES | Messagebox.NO, Messagebox.QUESTION,
						new EventListener() {
							public void onEvent(Event evt) {
								switch (((Integer) evt.getData()).intValue()) {
								case Messagebox.YES:
									copyOrMoveFile(fileToCopy);
									break;
								}
							}
						});
			} catch (InterruptedException e) {
				messagesModel.addMessage(new Message("common.msg.unexpected_exception", MessageType.ERROR));
			}
		} else {
			copyOrMoveFile(fileToCopy);
		}
	}

	private void copyOrMoveFile(File fileToCopy) {
		if (fileToCopy != null) {
			try {
				if (isCutButtonClicked) {
					if (!fileToCopy.getAbsolutePath().equals(
							directoryManagerModel.getWorkspaceDirectory())) {
						fileSystemService.moveToDirectory(fileToCopy, new File(
								directoryManagerModel.getWorkspaceDirectory()));
					} else {
						ZKUtils.showWarning("filemanager.msg.recursive_move");
					}
				} else {
					if (!fileToCopy.getAbsolutePath().equals(
							directoryManagerModel.getWorkspaceDirectory())) {
						fileSystemService.copyToDirectory(fileToCopy, new File(
								directoryManagerModel.getWorkspaceDirectory()));
					} else {
						ZKUtils.showWarning("filemanager.msg.recursive_copy");
					}
				}
			} catch (FileSystemException fse) {
				handleMLexception(fse);
			}
			directoryManagerModel.setFileToCopy(null);
			initFileListModel();
		}
	}

	public void onUpload$uploadButton(UploadEvent e) {
		Media media = e.getMedia();
		String fileName = getDirectoryManagerModel().getWorkspaceDirectory()
				+ JefbUtils.FILE_SEPARATOR + media.getName();

		InputStream streamData = null;
		if (media.isBinary()) {
			streamData = media.getStreamData();
		} else {
			String stringData = media.getStringData();
			streamData = new ByteArrayInputStream(stringData.getBytes());
		}
		if (streamData != null) {
			try {
				fileSystemService.writeFile(streamData, fileName);
			} catch (FileSystemException fse) {
				handleMLexception(fse);
			}
		}
		initFileListModel();
	}

	public void onClick$navUpButton(Event e) {
		String currentSubpath = directoryManagerModel.getCurrentDir();
		if (!currentSubpath.equals(JefbUtils.FILE_SEPARATOR)
				&& !currentSubpath.equals(directoryManagerModel.getWorkspace())) {
			currentSubpath = currentSubpath.substring(0,
					currentSubpath.lastIndexOf(JefbUtils.FILE_SEPARATOR));
			if (currentSubpath.equals("")) {
				setCurrentDir(JefbUtils.FILE_SEPARATOR, NavAction.FORWARD);
			} else {
				setCurrentDir(currentSubpath, NavAction.FORWARD);
			}
			getDirectoryManagerModel().setSelectedFile(null);
			initFileListModel();
		}
		setFileStatusPanelVisibility();
	}

	public void onClick$navBackButton(Event event) {
		setCurrentDir(directoryManagerModel.getBackDirectories().pop(),
				NavAction.BACK);
		initFileListModel();
	}

	public void onClick$navForwardButton(Event event) {
		setCurrentDir(directoryManagerModel.getForwardDirectories().pop(),
				NavAction.FORWARD);
		initFileListModel();
	}

	public void onClick$navHomeButton(Event event) {
		setCurrentDir(JefbUtils.FILE_SEPARATOR, NavAction.FORWARD);
		initFileListModel();
	}

	public void onClick$deleteFileButton(Event e) {
		deleteSelectedFile();
	}

	public void onClick$zipFileButton(Event e) {
		FileDataHolder selectedFile = directoryManagerModel.getSelectedFile();
		if (selectedFile != null && selectedFile.getFile() != null) {
			try {
				fileSystemService.zipFile(selectedFile.getFile(), selectedFile
						.getFile().getName() + ".zip");
			} catch (FileSystemException fse) {
				handleMLexception(fse);
			}
			initFileListModel();
		}
	}

	private void deleteSelectedFile() {
		final FileDataHolder selectedFile = directoryManagerModel
				.getSelectedFile();
		String fileName = selectedFile.getFile().getName();
		try {
			// TODO make message box optional -->user settings
			Messagebox.show(
					ZKUtils.getLabel("filenamager.msg.delete_file", fileName),
					ZKUtils.getLabel("filemanager.prompt.delete_file"),
					Messagebox.YES | Messagebox.NO, Messagebox.QUESTION,
					new EventListener() {
						public void onEvent(Event evt) {
							switch (((Integer) evt.getData()).intValue()) {
							case Messagebox.YES:
								deleteFile(selectedFile);
								break;
							}
						}
					});
		} catch (InterruptedException e) {
			messagesModel.addMessage(new Message(
					"common.msg.unexpected_exception", MessageType.ERROR));
		}
	}

	private void deleteFile(final FileDataHolder selectedFile) {
		try {
			if (selectedFile.getFile().isDirectory()) {
				if (fileSystemService.isDirectoryEmpty(selectedFile.getFile())) {
					fileSystemService.deleteFile(selectedFile.getFile(),
							directoryManagerModel.getWorkspace(),
							userSessionService.getHomeDir());
				} else {
					try {
						String fileName = selectedFile.getFile().getName();
						Messagebox
								.show(ZKUtils.getLabel(
										"filemanager.msg.nonempty_directory",
										fileName),
										ZKUtils.getLabel("filemanager.prompt.nonempty_directory"),
										Messagebox.YES | Messagebox.NO,
										Messagebox.QUESTION,
										new EventListener() {
											public void onEvent(Event evt) {
												switch (((Integer) evt
														.getData()).intValue()) {
												case Messagebox.YES:
													fileSystemService.deleteFile(
															selectedFile
																	.getFile(),
															directoryManagerModel
																	.getWorkspace(),
															userSessionService
																	.getHomeDir());
													initFileListModel();
													break;
												}
											}
										});
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			} else {
				fileSystemService.deleteFile(selectedFile.getFile(),
						directoryManagerModel.getWorkspace(),
						userSessionService.getHomeDir());
			}
		} catch (FileSystemException fse) {
			handleMLexception(fse);
		}
		initFileListModel();
	}

	public void onClick$downloadFileButton(Event event) {
		try {
			if (directoryManagerModel.getSelectedFile() != null) {
				Filedownload.save(directoryManagerModel.getSelectedFile()
						.getFile().getAbsoluteFile(), null);
			}
		} catch (FileNotFoundException e) {
			messagesModel.addMessage(new Message(
					"filemanager.msg.file_doesnt_exist", MessageType.ERROR));
		}
	}

	public void onClick$editFileButton(Event e) {
		editFile();
	}

	public void onOK$editFileNameTextBox(Event event) {
		editFile();
	}

	private void editFile() {
		FileDataHolder selectedFile = directoryManagerModel.getSelectedFile();
		if (!selectedFile.getFile().equals(
				directoryManagerModel.getSelectedFile().getFileName())) {
			try {
				fileSystemService.renameFile(selectedFile.getFile(),
						selectedFile.getFileName(),
						directoryManagerModel.getWorkspace(),
						userSessionService.getHomeDir());
			} catch (FileSystemException fse) {
				handleMLexception(fse);
			}
		}
		initFileListModel();
	}

	public TransmissionStatus getTransmissionStatus(FileEntity fileEntity,
			DestinationEntity destinationEntity) {
		return transmissionStatusService.getTransmissionStatus(fileEntity,
				destinationEntity);
	}

	public void setFileStatusPanelVisibility() {
		setFileHandlerComponentsVisibility(directoryManagerModel
				.getSelectedFile() != null);
	}

	private void setFileHandlerComponentsVisibility(boolean visible) {
		fileInfoGrid.setVisible(visible);
		deleteFileButton.setVisible(visible);
		downloadFileButton.setVisible(visible
				&& directoryManagerModel.getSelectedFile() != null
				&& directoryManagerModel.getSelectedFile().getIsFile());
		// editFileButton.setVisible(visible);
		markForCopyButton.setVisible(visible);
		markForCutButton.setVisible(visible);
		markForCutButton.setVisible(visible);
		zipFileButton.setVisible(visible);
		pasteFileButton
				.setVisible(directoryManagerModel.getFileToCopy() != null);
		renameButton.setVisible(visible);
	}

	public void onCreate$outboxWindow(Event e) {
		setFileStatusPanelVisibility();
	}

	public void onSelect$fileList(SelectEvent event) {
		FileDataHolder fileDataHolder = directoryManagerModel.getSelectedFile();
		if (fileDataHolder != null && fileDataHolder.getFile() != null) {
			setFileStatusPanelVisibility();
		}
	}

	public class AssignedDestinationsModel extends ListModelList implements
			RowRenderer {

		private static final long serialVersionUID = 1L;

		public AssignedDestinationsModel() {
			super();
		}

		public void render(Row row, Object data) throws Exception {
			final DestinationEntity dest = (DestinationEntity) data;
			row.appendChild(new Label(dest.getName()));
			TransmissionStatus transmissionStatus = getTransmissionStatus(
					directoryManagerModel.getSelectedFile().getFileEntity(),
					dest);
			row.appendChild(new Label(transmissionStatus
					.getTransmittedPercent().toString() + "%"));
			row.setAttribute("assignedDestination", data);
		}

	}

	public void setFileRegisterService(IFileRegisterService fileRegisterService) {
		this.fileRegisterService = fileRegisterService;
	}

	public IFileRegisterService getFileRegisterService() {
		return fileRegisterService;
	}

	public void setFileSystemService(IFileSystemService fileSystemService) {
		this.fileSystemService = fileSystemService;
	}

	public IFileSystemService getFileSystemService() {
		return fileSystemService;
	}

	public void setTransmissionStatusService(
			ITransmissionStatusService transmissionStatusService) {
		this.transmissionStatusService = transmissionStatusService;
	}

	public ITransmissionStatusService getTransmissionStatusService() {
		return transmissionStatusService;
	}

	public void setCommonPersistenceService(
			ICommonPersistenceService commonPersistenceService) {
		this.commonPersistenceService = commonPersistenceService;
	}

	public ICommonPersistenceService getCommonPersistenceService() {
		return commonPersistenceService;
	}

	public void setDirectoryManagerModel(
			DirectoryMananagerModel directoryManagerModel) {
		this.directoryManagerModel = directoryManagerModel;
	}

	public DirectoryMananagerModel getDirectoryManagerModel() {
		return directoryManagerModel;
	}

	public void onOK() {
		FileDataHolder selectedFile = directoryManagerModel.getSelectedFile();
		if (selectedFile != null && selectedFile.getFile() != null) {
			File file = selectedFile.getFile();
			if (file.isDirectory()) {
				enterDir(selectedFile);
			}
		}
	}

	public class FileListModel extends BindingListModelList implements
			ListitemRenderer {

		private static final long serialVersionUID = -7028321494286220589L;

		public FileListModel(List<FileDataHolder> list) {
			super(list, false);
		}

		public void render(Listitem li, Object data) {
			final FileDataHolder fileHolder = (FileDataHolder) data;
			if (fileHolder.getFile() != null) {
				Listcell cell = new Listcell(fileHolder.getFile().getName());
				cell.setParent(li);
				if (fileHolder.getFile().isDirectory()) {
					if(fileHolder.getFile().canRead()){
						cell.setImage("../img/fs16/folder.png");
					}else{
						cell.setImage("../img/fs16/folder_red2.png");
					}
					
					final Listcell calcDirSizeCell = new Listcell();
					final Button calcDirSizeButton = new Button(
							ZKUtils.getLabel("filemanager.filelist.button.calculate"));
					calcDirSizeButton.addEventListener(Events.ON_CLICK,
							new EventListener() {
								public void onEvent(Event event)
										throws Exception {
									Long directorySize = fileSystemService
											.calculateSizeOfDirectory(fileHolder
													.getFile());
									calcDirSizeButton.setLabel(WebUtil
											.convertByteLength(directorySize));
								}
							});
					calcDirSizeButton.setParent(calcDirSizeCell);
					calcDirSizeCell.setParent(li);
				} else {
					cell.setImage("../img/fs16/"
							+ Icons.getSrc(fileHolder.getFile().getName()));
					Listcell fileLenthCell = new Listcell(
							WebUtil.convertByteLength(fileHolder.getFile()
									.length()));
					fileLenthCell.setParent(li);
				}
				if (fileHolder.getFile().isFile()) {
					cell.addEventListener(Events.ON_DOUBLE_CLICK,
							new EventListener() {
								public void onEvent(Event event)
										throws Exception {
									ComponentsUtil.createEditorTab(fmTabbox,
											fileHolder.getFile());

								}
							});

				}
				if (fileHolder.getFile().isDirectory()) {
					cell.addEventListener(Events.ON_DOUBLE_CLICK,
							new EventListener() {
								public void onEvent(Event event)
										throws Exception {
									enterDir(fileHolder);
								}
							});

					cell.addEventListener(Events.ON_OK, new EventListener() {
						public void onEvent(Event event) throws Exception {
							enterDir(fileHolder);
						}
					});
				}
				li.setAttribute("fileDataHolder", data);

				li.setCtrlKeys("#del^c^x^v");
				li.addEventListener(Events.ON_CTRL_KEY,
						new FileListKeyEventListener());

				li.setDraggable("true");
				li.setDroppable("true");
				li.addEventListener(Events.ON_DROP,
						new FileListDropEventListener());
			} else {
				Listcell editCell = new Listcell();
				editCell.setParent(li);
				Textbox editBox = new Textbox();
				editBox.setParent(editCell);
				editBox.setFocus(true);
				editBox.setWidth("98%");
				editBox.addEventListener(Events.ON_BLUR, new EventListener() {
					public void onEvent(Event event) throws Exception {
						create(event, fileHolder);
					}
				});
				editBox.addEventListener(Events.ON_OK, new EventListener() {
					public void onEvent(Event event) throws Exception {
						create(event, fileHolder);
					}
				});
			}
		}

		private void create(Event event, FileDataHolder fileHolder) {
			Textbox box = (Textbox) event.getTarget();
			if (box.getValue() != null && !box.getValue().isEmpty()) {
				String dirName = userSessionService.getHomeDir()
						+ getDirectoryManagerModel().getCurrentDir()
						+ JefbUtils.FILE_SEPARATOR + box.getValue();
				try {
					if (fileHolder.getIsFile()) {
						fileSystemService.createFile(dirName);
					} else {
						fileSystemService.createDir(dirName);
					}
				} catch (FileSystemException fse) {
					handleMLexception(fse);
				}
			}
			initFileListModel();
		}
	}

	private void enterDir(FileDataHolder fileHolder) {
		String currentSubpath = directoryManagerModel.getCurrentDir();
		if (currentSubpath.equals(JefbUtils.FILE_SEPARATOR)) {
			currentSubpath = currentSubpath + fileHolder.getFile().getName();
		} else {
			currentSubpath = currentSubpath + JefbUtils.FILE_SEPARATOR
					+ fileHolder.getFile().getName();
		}
		setCurrentDir(currentSubpath, NavAction.FORWARD);
		initFileListModel();
	}

	private void setCurrentDir(String currentDir, NavAction navAction) {
		directoryManagerModel.setCurrentDir(currentDir, navAction);
		refreshNavButtons();
	}

	private void refreshNavButtons() {
		navBackButton.setDisabled(directoryManagerModel
				.getBackDirectoriesAreEmpty());
		navForwardButton.setDisabled(directoryManagerModel
				.getForwardDirectoriesAreEmpty());
		navHomeButton.setDisabled(directoryManagerModel.isCurrentDirRoot());
		navUpButton.setDisabled(directoryManagerModel.isCurrentDirRoot());
	}

	public void setUserSession(IUserSessionService userSessionService) {
		this.userSessionService = userSessionService;
	}

	public IUserSessionService getUserSession() {
		return userSessionService;
	}

	public void setMessagesModel(MessagesModel messagesModel) {
		this.messagesModel = messagesModel;
	}

	public MessagesModel getMessagesModel() {
		return messagesModel;
	}

	private class FileListKeyEventListener implements EventListener {

		public void onEvent(Event event) throws Exception {
			if (event instanceof KeyEvent) {
				KeyEvent keyEvent = (KeyEvent) event;
				switch (keyEvent.getKeyCode()) {
				case 46:// delete
					deleteSelectedFile();
					break;
				}

				if (keyEvent.isCtrlKey()) {
					switch (keyEvent.getKeyCode()) {
					case 88:// ctrl+x
						onClick$markForCutButton(event);
						break;
					case 67:// ctrl+c
						onClick$markForCopyButton(event);
						break;
					case 86:// ctrl+v
						onClick$pasteFileButton(event);
						break;
					}
				}
			}

		}

	}

	private class FileListDropEventListener implements EventListener {
		public void onEvent(Event event) throws Exception {
			if (event instanceof DropEvent) {
				DropEvent dropEvent = (DropEvent) event;
				Component component = dropEvent.getTarget();
				if (component instanceof Listitem) {
					Listitem targetListitem = (Listitem) component;
					final FileDataHolder targetFileDataHolder = (FileDataHolder) targetListitem
							.getAttribute("fileDataHolder");
					if (targetFileDataHolder.getFile() != null
							&& targetFileDataHolder.getFile().isDirectory()) {
						Listitem draggedListItem = (Listitem) dropEvent
								.getDragged();
						final FileDataHolder draggedFileHolder = (FileDataHolder) draggedListItem
								.getAttribute("fileDataHolder");

						boolean containsFile = fileSystemService.containsFile(
								targetFileDataHolder.getFile(),
								draggedFileHolder.getFile());
						if (containsFile) {
							String fileName = draggedFileHolder.getFile()
									.getName();
							Messagebox
									.show(ZKUtils
											.getLabel(
													"filemanager.msg.file_already_exists",
													fileName),
											ZKUtils.getLabel("filemanager.prompt.file_already_exists"),
											Messagebox.YES | Messagebox.NO,
											Messagebox.QUESTION,
											new EventListener() {
												public void onEvent(Event evt) {
													switch (((Integer) evt
															.getData())
															.intValue()) {
													case Messagebox.YES:
														fileSystemService
																.moveToDirectory(
																		draggedFileHolder
																				.getFile(),
																		targetFileDataHolder
																				.getFile());
														initFileListModel();
														break;
													}
												}
											});
						} else {
							fileSystemService.moveToDirectory(
									draggedFileHolder.getFile(),
									targetFileDataHolder.getFile());
						}

					}
				}
				initFileListModel();
			}
		}
	}

	private void handleMLexception(MLException mlException) {
		messagesModel.addMessage(new Message(mlException.getMsgKey(),
				MessageType.ERROR));
	}
}
